package arm.db.tools;

import arm.common.entity.IBaseEntity;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
import java.util.List;
import java.util.Map;

public class DBManager
{


    private  static EntityManagerFactory entityManagerFactory = null;

    /**
     * Получение экземпляра объекта с настройками
     * @return EntityManagerFactory
     */
    private static EntityManagerFactory getEntityManagerFactory() {
        if (entityManagerFactory == null){
            entityManagerFactory = Persistence.createEntityManagerFactory("ArmPU");
        }
        return entityManagerFactory;
    }

    /**
     * Получение EntityManager
     * @return EntityManager
     */
    public static synchronized EntityManager getEntityManager(){
        if (entityManagerFactory == null){
            entityManagerFactory = getEntityManagerFactory();
        }
        return entityManagerFactory.createEntityManager();
    }

    /**
     * Сохранение объекта в базе данных.
     * Изменение при имеющемся и создание нового, если такого объекта нет в базе данных
     * @param  object Объект, который нужно сохранить
     * @return сохраненный объект
     */
    public static <T> T saveOrUpdate(T object) {
        if (object == null) {
            System.err.println("DBManager.saveOrUpdate(null) is called");
            return null;
        }
        EntityManager em = getEntityManager();
        T merge = null;
        EntityTransaction tx = null;
        try {
            tx = em.getTransaction();
            tx.begin();
            merge = saveOrUpdate(em, object);
            tx.commit();
        } catch (RuntimeException re) {
            if (tx != null && tx.isActive()) tx.rollback();
            re.printStackTrace();
        } finally {
            em.close();
        }
        return merge;
    }

    /**
     * Сохранение объекта в базе данных.
     * Изменение при имеющемся и создание нового, если такого объекта нет в базе данных
     * @param  object Объект, который нужно сохранить
     * @param  em EntityManager
     * @return сохраненный объект
     */
    public static <T> T saveOrUpdate(EntityManager em, T object) {
        T merge;
        merge = em.merge(object);
        return merge;
    }

    public static List readList (String className)
    {
        return getEntityManager().createQuery("FROM " + className).getResultList();
    }


    public static <T> T find(Class<T> cl, Long selectedId)
    {
        return getEntityManager().find(cl, selectedId);
    }

    public static void delete(IBaseEntity object)
    {
        EntityManager em = getEntityManager();
        EntityTransaction tx = null;
        try {
            tx = em.getTransaction();
            tx.begin();
            em.remove(em.find(object.getClass(),object.getId()));
            tx.commit();
        } catch (RuntimeException re) {
            if (tx != null && tx.isActive()) tx.rollback();
            re.printStackTrace();
        } finally {
            em.close();
        }

    }

    public static List readSQLList(String sql)
    {
        return getEntityManager().createNativeQuery(sql).getResultList();
    }
}
